#pragma once
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

namespace bit
{
    std::string default_pipe("mypipe");
#define BUFF_SIZE 4096
    class NamedPipe_Write
    {
    public:
        NamedPipe_Write(const std::string &path = default_pipe)
            : _path(path)
        {
            if (mkfifo(_path.c_str(), 0666) == -1)
                std::cerr << "pipe: " << strerror(errno) << std::endl;
            _fd = open(_path.c_str(), O_WRONLY);
            if (_fd == -1)
            {
                perror("NamedPipe_Write fail");
                exit(errno);
            }
        }
        ~NamedPipe_Write()
        {
            if (unlink(_path.c_str()) == -1)
                std::cerr << "unlink: " << strerror(errno) << std::endl;
            if (_fd != -1)
                close(_fd);
        }
        void Write(const std::string &message)
        {
            write(_fd, message.c_str(), message.size());
        }

    private:
        int _fd;
        std::string _path;
    };

    class NamedPipe_Read
    {
    public:
        NamedPipe_Read(const std::string &path = default_pipe)
            : _path(path)
        {
            _fd = open(_path.c_str(), O_RDONLY);
            if (_fd == -1)
            {
                perror("NamedPipe_Read fail");
                exit(errno);
            }
        }
        ~NamedPipe_Read()
        {
            if (_fd != -1)
                close(_fd);
        }
        // Read函数的返回值是读取到的字节数。
        int Read(std::string &out)
        {
            char buff[BUFF_SIZE] = {0};
            int n = read(_fd, buff, BUFF_SIZE);
            if (n > 0)
            {
                buff[n] = 0;
                out = buff;
            }
            return n;
        }
        int Read(char *out)
        {
            char buff[BUFF_SIZE] = {0};
            int n = read(_fd, buff, BUFF_SIZE);
            if (n > 0)
            {
                buff[n] = 0;
                if (strlen(buff) <= strlen(out))
                    strcpy(out, buff);
                else
                {
                    std::cerr << "Warning: There may be data loss!" << std::endl;
                    strncpy(out, buff, strlen(out) - 1);
                    n = strlen(out) - 1;
                }
            }
            return n;
        }

    private:
        int _fd;
        std::string _path;
    };
}